package org.liu;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

/**
 * Created by liu on 15-5-20.
 */
public class OldDrawer extends JFrame {
    public static final int U_SZ = 16;
    public static final int WIDTH = 534;
    public static final int HEIGHT = 580;
    public static final int GROUND_X = 50;
    public static final int GROUND_Y = 50;
    public static final int GROUND_W = 320;
    public static final int GROUND_H = 480;
    public static final int NEXT_X = 420;
    public static final int NEXT_Y = 50;
    public static final int NEXT_W = 64;
    public static final int NEXT_H = 64;
    public static final int SCORE_X = 420;
    public static final int SCORE_Y = 164;
    public static final int SCORE_W = 64;
    public static final int SCORE_H = 50;

    private Main main;
    private Image buffer;
    private Image welcome;
    private Image main_stage;

    public void setMain(Main main) {
        this.main = main;
    }

    public OldDrawer() {
        super();
        setSize(WIDTH, HEIGHT);
        setResizable(false);
        buffer = createImage(getWidth(), getHeight());
        this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                buffer = createImage(getWidth(), getHeight());
            }
        });
        try {
            welcome = ImageIO.read(getClass().getResourceAsStream("welcome.png"));
            main_stage = ImageIO.read(getClass().getResourceAsStream("main-stage.png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public OldDrawer(Main main) {
        this();
        setMain(main);
    }

    /**
     * Repaint an Entity and area around
     * @param e
     * @param dir direction 0: up 1: right 2: down(actually no direction, only the entity itself is repainted)
     *            3: left
     */
    public void repaintEntity(Entity e, int dir) {
        if(dir == 0) {
            repaint(GROUND_X + e.x * U_SZ - 1, GROUND_Y + (e.y - 1) * U_SZ - 1,
                    e.width * U_SZ + 2, (e.height + 1)* U_SZ + 2);
        } else if(dir == 1) {
            repaint(GROUND_X + e.x * U_SZ - 1, GROUND_Y + e.y * U_SZ - 1,
                    (e.width + 1) * U_SZ + 2, e.height * U_SZ + 2);
        } else if(dir == 2) {
            repaint(GROUND_X + e.x * U_SZ - 1, GROUND_Y + e.y * U_SZ - 1,
                    e.width * U_SZ + 2, e.height * U_SZ + 2);
        } else {
            repaint(GROUND_X + (e.x - 1) * U_SZ - 1, GROUND_Y + e.y * U_SZ - 1,
                    (e.width + 1) * U_SZ + 2, e.height * U_SZ + 2);
        }
    }
    public void repaintGround() {
        repaint(GROUND_X - 1, GROUND_Y - 1, GROUND_W + 2, GROUND_H + 2);
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

    @Override
    public void paint(Graphics g) {
        Graphics tmpg = buffer.getGraphics();
        tmpg.setColor(Main.COLOR_BACKGROUND);
        if(main.inGame || main.printGameOver) {
            tmpg.drawImage(main_stage, 0, 0, null);
            tmpg.setColor(Main.COLOR_FOREGROUND);
            paintGround(tmpg, main.ground);
            paintEntity(tmpg, main.currEntity);
            paintNext(tmpg, main.nextEntity);
            paintScore(tmpg, main.score);
            if (main.printGameOver) { // print game over
                tmpg.setColor(Main.COLOR_BLUE_MAGENTA);
                Font f = Font.decode("Arial").deriveFont(Font.BOLD, 72);
                tmpg.setFont(f);
                tmpg.drawString("Game Over", 100, 300);
            }
        } else { // print welcome
            tmpg.drawImage(welcome, 0, 0, null);
        }
        g.drawImage(buffer, 0, 0, getWidth(), getHeight(), null);
    }

    private static void paintGround(Graphics g, Ground ground) {
        g.translate(GROUND_X, GROUND_Y);
        for(int x = 0; x < Ground.WIDTH; ++x) {
            for(int y = 0; y < Ground.HEIGHT; ++y) {
                if(ground.data[y][x] != Main.BLOCK_NONE) {
                    g.setColor(blockToColor(ground.data[y][x]));
                    g.fillRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                    g.setColor(Main.COLOR_FOREGROUND);
                    g.drawRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                }
            }
        }
        g.translate(-GROUND_X, -GROUND_Y);
    }

    private static void paintEntity(Graphics g, Entity e) {
        g.translate(GROUND_X + e.x * U_SZ, GROUND_Y + e.y * U_SZ);
        for(int x = 0; x < e.width; ++x) {
            for(int y = 0; y < e.height; ++y) {
                if(e.data[y][x] != 0) {
                    g.setColor(blockToColor(e.color));
                    g.fillRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                    g.setColor(Main.COLOR_FOREGROUND);
                    g.drawRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                }
            }
        }
        g.translate(- GROUND_X - e.x * U_SZ, -GROUND_Y - e.y * U_SZ);
    }

    private static Color blockToColor(int block) {
        if(block == Main.BLOCK_CYAN) return Main.COLOR_CYAN;
        else if(block == Main.BLOCK_BLUE_MAGENTA) return Main.COLOR_BLUE_MAGENTA;
        else if(block == Main.BLOCK_MAGENTA) return Main.COLOR_MAGENTA;
        else if(block == Main.BLOCK_LIGHT_GREY) return Main.COLOR_LIGHT_GREY;
        else if(block == Main.BLOCK_LIME) return Main.COLOR_LIME;
        else if(block == Main.BLOCK_YELLOW) return Main.COLOR_YELLOW;
        else if(block == Main.BLOCK_RED) return Main.COLOR_RED;
        else return null;
    }

    private static void paintNext(Graphics g, Entity e) {
        int sx = e.width, sy = e.height, ex = 0, ey = 0;
        for(int xi = 0; xi < e.width; ++xi) {
            for(int yi = 0; yi < e.height; ++yi) {
                if(e.data[yi][xi] != 0) {
                    if(sx > xi) sx = xi;
                    if(sy > yi) sy = yi;
                    if(ex < xi) ex = xi;
                    if(ey < yi) ey = yi;
                }
            }
        }

        g.setColor(Main.COLOR_FOREGROUND);
        g.translate(NEXT_X, NEXT_Y);

        int width = ex - sx;
        int height = ey - sy;
        int startx = ((4 - width) / 2 - sx) * U_SZ;
        int starty = ((4 - height) / 2 - sy) * U_SZ;
        g.translate(startx, starty);

        for(int x = 0; x < e.width; ++x) {
            for(int y = 0; y < e.height; ++y) {
                if(e.data[y][x] != 0) {
                    g.setColor(blockToColor(e.color));
                    g.fillRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                    g.setColor(Main.COLOR_FOREGROUND);
                    g.drawRect(x * U_SZ, y * U_SZ, U_SZ, U_SZ);
                }
            }
        }

        g.translate(-startx, -starty);

        g.translate(-NEXT_X, -NEXT_Y);
    }

    private static void paintScore(Graphics g, int score) {
        g.translate(SCORE_X, SCORE_Y);
        if(g instanceof Graphics2D) {
            Stroke origin = ((Graphics2D) g).getStroke();
            ((Graphics2D) g).setStroke(new BasicStroke(5));
            g.setFont(Font.decode("Arial").deriveFont(Font.BOLD, 12));
            g.setColor(Main.COLOR_BACKGROUND);
            g.drawString(String.format("SCORE: %d", score), 2, 30);

            ((Graphics2D) g).setStroke(origin);
        }
        g.translate(-SCORE_X, -SCORE_Y);
    }
}
